/*
 * Contact.java
 *
 * Created on 13 Май 2008 г., 15:39
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.jimm.protocol;

import java.util.ArrayList;
import java.util.List;

import org.jimm.app.ContactListActivity;
import org.jimm.app.JimmApplication;
import org.jimm.app.R;
import org.jimm.message.PlainMessage;
import org.jimm.service.Preferences;

import android.text.TextUtils;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.View;

/**
 * @author vladimir, r.u.s.h.a.n.
 */
abstract public class Contact implements TreeNode {

    public final boolean isOnline() {
        return (StatusInfo.STATUS_OFFLINE != status);
    }

    private View convertView;
    protected String userId;
    private String name;
    private int groupId = Group.NOT_IN_GROUP;
    private int booleanValues;
    private int status = StatusInfo.STATUS_OFFLINE;
    private String statusText = null;
    private int xstatus = XStatusInfo.XSTATUS_NONE;
    private String xstatusText = null;
    public final List<PlainMessage> messages = new ArrayList<PlainMessage>();
    private Preferences p = JimmApplication.getInstance().getPreferences();

    public void setConvertView(View convertView) {
        this.convertView = convertView;

    }

    public View getConvertView() {
        return convertView;
    }

    public final String getUserId() {
        return userId;
    }

    public final String getName() {
        return name;
    }

    public void setName(String newName) {
        if (!TextUtils.isEmpty(newName)) {
            name = newName;
        }
    }

    public final void setGroupId(int id) {
        groupId = id;
    }

    public final int getGroupId() {
        return groupId;
    }

    public final void setGroup(Group group) {
        setGroupId((null == group) ? Group.NOT_IN_GROUP : group.getId());
    }

    public String getDefaultGroupName() {
        return null;
    }

    public final Protocol getProtocol() {
        return JimmApplication.getInstance().getAccountsManager().getProtocol(this);
    }

    ///////////////////////////////////////////////////////////////////////////
    public final void setXStatus(int index, String text) {
        xstatus = index;
        xstatusText = (XStatusInfo.XSTATUS_NONE == index) ? null : text;
    }

    public final int getXStatusIndex() {
        return xstatus;
    }

    public final int getXStatusIcon() {
        return XStatusInfo.getIcon(getXStatusIndex() + 1);
    }

    public final String getXStatusText() {
        return xstatusText;
    }

    ///////////////////////////////////////////////////////////////////////////
    public void setOfflineStatus() {
        setStatus(StatusInfo.STATUS_OFFLINE, null);
        setXStatus(XStatusInfo.XSTATUS_NONE, null);
        beginTyping(false);
    }

    public final int getStatusIndex() {
        return status;
    }

    public final int getStatusIcon() {
        return getStatusIcon(getStatusIndex());
    }

    public final int getStatusIcon(int index) {
        Protocol p = getProtocol();
        if (p != null)
            return p.getStatusInfo().getIcon(index);

        return 0;
    }

    public final String getStatusText() {
        return statusText;
    }

    protected final void setStatus(int statusIndex, String text) {
        status = statusIndex;
        statusText = (StatusInfo.STATUS_OFFLINE == status) ? null : text;
    }

///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////
    /* Activates the contact item menu */
    public void activate(Protocol p) {
//        ContactList.getInstance().setCurrentContact(this);

//        ChatTextList chat = p.getChat(this);
//        if (hasChat()) {
//            chat.activate();
//        } else {
//            chat.writeMessage(null);
//        }
    }
///////////////////////////////////////////////////////////////////////////
    // 00000000 | messageIconIndex | 00000000 | 00000000

    public static final byte CONTACT_NO_AUTH = 1 << 1; /* Boolean */
    private static final byte CONTACT_IS_TEMP = 1 << 3; /* Boolean */
    //public static final byte B_AUTOANSWER          = 1 << 2; /* Boolean */
    public static final byte SL_VISIBLE = 1 << 4; /* Boolean */
    public static final byte SL_INVISIBLE = 1 << 5; /* Boolean */
    public static final byte SL_IGNORE = 1 << 6; /* Boolean */

    private static final int TYPING = 1 << 8; /* Boolean */
    private static final int HAS_CHAT = 1 << 9; /* Boolean */

    public final void setBooleanValue(byte key, boolean value) {
        if (value) {
            booleanValues |= key;
        } else {
            booleanValues &= ~key;
        }
    }

    public final boolean isTemp() {
        return (booleanValues & CONTACT_IS_TEMP) != 0;
    }

    public final boolean isAuth() {
        return (booleanValues & CONTACT_NO_AUTH) == 0;
    }

    public final void setBooleanValues(byte vals) {
        booleanValues = (booleanValues & ~0xFF) | (vals & 0x7F);
    }

    public final byte getBooleanValues() {
        return (byte) (booleanValues & 0x7F);
    }

    public final void setTempFlag(boolean isTemp) {
        setBooleanValue(Contact.CONTACT_IS_TEMP, isTemp);
    }

    public final void beginTyping(boolean typing) {
        if (typing && isOnline()) {
            booleanValues |= TYPING;
        } else {
            booleanValues &= ~TYPING;
        }
    }

    public final boolean isTyping() {
        return (booleanValues & TYPING) != 0;
    }

    public final boolean hasChat() {
        return (booleanValues & HAS_CHAT) != 0;
    }

    public final void updateChatState(boolean state) {
        if (state) {
            booleanValues |= HAS_CHAT;
        } else {
            booleanValues &= ~HAS_CHAT;
        }
    }


    public final boolean inVisibleList() {
        return (booleanValues & SL_VISIBLE) != 0;
    }

    public final boolean inInvisibleList() {
        return (booleanValues & SL_INVISIBLE) != 0;
    }

    public final boolean inIgnoreList() {
        return (booleanValues & SL_IGNORE) != 0;
    }

    protected final void initPrivacyMenu(ContextMenu menu) {
        if (!isTemp()) {
//            String visibleList = inVisibleList()
//                    ? "rem_visible_list" : "add_visible_list";
//            String invisibleList = inInvisibleList()
//                    ? "rem_invisible_list": "add_invisible_list";
//            String ignoreList = inIgnoreList()
//                    ? "rem_ignore_list": "add_ignore_list";

//            menu.add(visibleList,   USER_MENU_PS_VISIBLE);
//            menu.add(invisibleList, USER_MENU_PS_INVISIBLE);
//            menu.add(ignoreList,    USER_MENU_PS_IGNORE);
        }
    }
    // #sijapp cond.end #

    public String getMyName() {
        return getProtocol().getNick();
    }

///////////////////////////////////////////////////////////////////////////

    public boolean isSingleUserContact() {
        return true;
    }

    public boolean hasHistory() {
        return !isTemp();
    }

    ///////////////////////////////////////////////////////////////////////////
    public boolean isVisibleInContactList() {
        return isOnline() || hasChat() || isTemp() || (!p.hideOfflineContacts);
    }

    /* Returns color for contact name */
    public final int getTextColor() {
        if (isTemp()) {
            return R.color.contact_temp;
        }
        if (hasChat()) {
            return R.color.contact_with_chat;
        }
        if (isOnline()) {
            return R.color.contact_online;
        }
        return R.color.contact_offline;
    }

    public final String getText() {
        return name;
    }

    // Node weight declaration.
    // -3       - normal group
    // -2       - non editable group
    // -1       - non removable group
    //  9       - chat group (online)
    // 10       - contact with message
    // 20 - 49  - normal-contact (status)
    // 50       - chat group (offline)
    // 51       - offline-contact
    // 60       - temp-contact
    public final int getNodeWeight() {
        // #sijapp cond.if protocols_JABBER is "true" #
        if (!isSingleUserContact()) {
            return isOnline() ? 9 : 50;
        }
        // #sijapp cond.end #
        if (p.sortUpWithMsg && getUnreadMessageCount() > 0) {
            return 10;
        }

        if (Preferences.SORT_BY_NAME == p.clSortBy) {
            return 20;
        }
        if (isOnline()) {
            switch (p.clSortBy) {
                case Preferences.SORT_BY_STATUS:
                    // 29 = 49 - 20 last normal status
                    return 20 + StatusInfo.getWidth(getStatusIndex());
                case Preferences.SORT_BY_ONLINE:
                    return 20;
            }
        }

        if (isTemp()) {
            return 60;
        }
        return 51;
    }

    ///////////////////////////////////////////////////////////////////////////
    public final int getUnreadMessageCount() {
        int count = 0;
        int n = messages.size();
        for (int i = 0; i < n; ++i) {
            if (!messages.get(i).isReaded())
                count++;
        }
        return count;
    }

    ///////////////////////////////////////////////////////////////////////////
    public static final int USER_MENU_MESSAGE = 1001;
    public static final int USER_MENU_PASTE = 1002;
    public static final int USER_MENU_QUOTE = 1003;

    public static final int USER_MENU_REQU_AUTH = 1004;

    public static final int USER_MENU_COPY_UID = 1006;
    public static final int USER_MENU_USER_REMOVE = 1007;
    public static final int USER_MENU_RENAME = 1009;
    //public static final int USER_MENU_LOCAL_INFO       = 1011;
    public static final int USER_MENU_USER_INFO = 1012;
    public static final int USER_MENU_MOVE = 1015;
    public static final int USER_MENU_STATUSES = 1016;
    public static final int USER_MENU_HISTORY = 1025;
    public static final int USER_MENU_ADD_USER = 1018;

    public static final int USER_MENU_GRANT_AUTH = 1021;
    public static final int USER_MENU_DENY_AUTH = 1022;


    public static final int USER_MENU_PS_VISIBLE = 1034;
    public static final int USER_MENU_PS_INVISIBLE = 1035;
    public static final int USER_MENU_PS_IGNORE = 1036;

    public static final int USER_MENU_USERS_LIST = 1037;
    public static final int USER_MANAGE_CONTACT = 1038;

    public static final int USER_MENU_WAKE = 13;
    public static final int USER_MENU_FILE_TRANS = 1005;
    public static final int USER_MENU_CAM_TRANS = 1006;

    public static final int CONFERENCE_DISCONNECT = 1040;

    ///////////////////////////////////////////////////////////////////////////
    protected abstract void initManageContactMenu(ContextMenu menu);

    protected void initContextMenu(ContextMenu contactMenu) {
        addChatItems(contactMenu);
        addGeneralItems(contactMenu);
    }

    public void addChatMenuItems(ContextMenu model) {
    }

    public final ContextMenu getContextMenu(ContextMenu menu, ContactListActivity a) {
        return new ContactMenu(getProtocol(), this, a).getContextMenu(menu);
    }

    protected final void addChatItems(ContextMenu menu) {
        if (isSingleUserContact()) {
            menu.add(Menu.FIRST, USER_MENU_MESSAGE, 2, R.string.msg_send);
            if (!isAuth()) {
                menu.add(Menu.FIRST, USER_MENU_REQU_AUTH, 2, R.string.requauth);
            }
        }
        if (!JimmApplication.isClipBoardEmpty()) {
            menu.add(Menu.FIRST, Contact.USER_MENU_PASTE, 2, android.R.string.paste);
            menu.add(Menu.FIRST, Contact.USER_MENU_QUOTE, 2, R.string.quote);
        }
        if (isSingleUserContact() || isOnline()) {
            addChatMenuItems(menu);
        }
    }

    protected final void addGeneralItems(ContextMenu menu) {
        menu.add(Menu.FIRST, USER_MENU_USER_INFO, 2, R.string.user_info);
        menu.add(Menu.FIRST, USER_MENU_COPY_UID, 2, R.string.copy_uin);

        //SubMenu sub = menu.addSubMenu(Menu.FIRST, USER_MANAGE_CONTACT, 2, R.string.manage);

        initManageContactMenu(menu);

        if (!isTemp()) {
            menu.add(Menu.FIRST, USER_MENU_HISTORY, 2, R.string.history);
        }
        if (isOnline()) {
            menu.add(Menu.FIRST, USER_MENU_STATUSES, 2, R.string.statuses);
        }


    }
}
